/*
NAME : RUSHIKESH M FANSE
DIV : H
ROLL NO : 16
ASSIGNMENT : DIFFERENT JOB SCHEDULNG
*/
#include<iostream>
#include<cstdio>
#include<fstream>
#include<list>
#include<algorithm>
#define MAX 10
using namespace std;
ifstream fin;
ofstream fout;
int time_quantum;
class process
{
	public:
	int p_id;
	int p_at;
	int p_bt;
	int p_rt;
	int p_tt;
	int p_wt;
	int p_pri;
	process(int pid,int pat,int pbt,int ppri)
	{			
		p_id=pid;
		p_at=pat;
		p_bt=pbt;
		p_rt=pbt;
		p_pri=ppri;
		p_tt=0;
		p_wt=0;
	}
};
int process_intel[MAX][MAX];
string str;
list<process> remaining_process;
int row,approach;
//initialize old current time and new current time
//current time can be updated as minimum of arrival time 
int old_current_time,new_current_time;
bool burstime(const process &a, const process &b)
{ 
	return a.p_bt < b.p_bt;
}

bool priority(const process &a, const process &b)
{ 
	return a.p_pri < b.p_pri;
}

process select_next(int approach)
{
	//different approaches to follow on users entry
	process min_burst_pro(0,0,0,0);
	int min;
	switch(approach)
	{
		case 1:
		{
			//FCFS APPROACH
			return remaining_process.front();
			
		}
		break;
		
		case 2:
		{
			//SHORTEST JOB FIRST APPROACH PREMPTIVE	
		}		
		case 3:
		{	
			//SHORTEST JOB FIRST APPROACH NON PREMPTIVE
			remaining_process.sort(burstime);
			return remaining_process.front();
		}
		break;
		case 4:
			//PRIORITY PREMPTIVE
		case 5:
		{
			//PRORITY NON PREMPTIVE
			remaining_process.sort(priority);
			return remaining_process.front();
		}
		break;
		
		case 6:
			//ROUND ROBIN
			time_quantum=2;
			return remaining_process.front();
		break;
	}
}
void add_into_remaining_process(int old_current_time,int new_current_time)
{
	for(int i=0;i<row;i++)
	{
		if(process_intel[i][1]>=old_current_time&&process_intel[i][1]<=new_current_time)
		{
			process p(process_intel[i][0],process_intel[i][1],process_intel[i][2],process_intel[i][3]);
			remaining_process.push_back(p);
		}	
	}
}
void removeprocess(int process_to_be_removed)
{
	list<process>::iterator it1;
	it1=remaining_process.begin();
	//advance(it1,process_to_be_removed-1);
	
	advance(it1,0);
	remaining_process.erase(it1);
}
void update_the_process_value(int p_id,int p_at,int p_bt,int p_rt,int p_tt,int p_wt,int p_pri)
{
	for(list<process>::iterator i=remaining_process.begin(),e=remaining_process.end();i!=e;i++)
			{
				
				if(i->p_id == p_id)
				{
					i->p_id=p_id;
					i->p_at=p_at;
					i->p_bt=p_bt;
					i->p_rt=p_rt;
					i->p_tt=p_tt;
					i->p_wt=p_wt;
					i->p_pri=p_pri;
				}
				
			}
}
int main()
{
	int flag;
	row=0;
	approach=1;
	char ch;
	//declare a matrix and read a file and store the problem in matrix
	fin.open("inputsc.txt");
	fout.open("output_scheduling.txt");
	while(!(fin.eof()))
	{
		getline(fin,str);
		if(!(str.empty()))
		{
			process_intel[row][0]=(int)str[0]-48;
			process_intel[row][1]=(int)str[2]-48;
			process_intel[row][2]=(int)str[4]-48;
			process_intel[row][3]=(int)str[6]-48;
			row++;
		}
	}
	while(approach<=6)
	{
		old_current_time=0;
		new_current_time=0;
		add_into_remaining_process(old_current_time,new_current_time);
		if(approach==1)
			cout<<"FCFS\n";
		else if(approach==2)
			cout<<"SHORTEST JOB PREMPTIVE\n";
		else if(approach==3)
			cout<<"SHORTEST JOB FIRST NON PREMPTIVE\n";
		else if(approach==4)
			cout<<"PRIORITY PREMPTIVE\n";
		else if(approach==5)
			cout<<"PRIORITY NON PREMPTIVE\n";
		else if(approach==6)
			cout<<"ROUND ROBIN \n";
		//get the remaning process at arrival time zero
		while(!(remaining_process.empty()))	
		{
			if(approach==6)//if(the approach used is round robin)
			{
				process p=select_next(approach);
			//	if(p.rt<=q)
			//	{
			//		ct+=p.rt;
			//		dequeue newly arrived process
			//	}
				if(p.p_rt<=time_quantum)
				{
					old_current_time=new_current_time;
					new_current_time+=p.p_rt;
					p.p_rt-=p.p_rt;
					p.p_tt=new_current_time-p.p_at;
					p.p_wt=p.p_tt-p.p_bt;
					printf("process id:%d   arrival time: %d  burst time:%d  turn around time:%d  waiting time:%d\n",p.p_id,p.p_at,p.p_bt,p.p_tt,p.p_wt);							
					flag=0;
					removeprocess(p.p_id);
					
				}
				else
				{
					flag=1;
					p.p_rt-=time_quantum;
					old_current_time=new_current_time;						
					new_current_time+=time_quantum;
					update_the_process_value(p.p_id,p.p_at,p.p_bt,p.p_rt,p.p_tt,p.p_wt,p.p_pri);
					removeprocess(p.p_id);
					remaining_process.push_back(p);
					
				}
				if(flag==0)
					add_into_remaining_process(old_current_time,new_current_time);
				else if(flag==1)	
					add_into_remaining_process(new_current_time,new_current_time);
			//	else
			//	{
			//		ct+=q;
			//		if(any new process has arrived)
			//		{
			//			inqueue it
			//		}
			//	}
			}
			else
			{
				//select next process to execute;
				process p=select_next(approach);
				//execute that process
				if((approach==2||approach==4)){//APPROACH IS PREMPTIVE
				//	here increment the new current time one by one 
				//	execute it 
				//	if finished remove it from current process
					if(p.p_rt==0)
					{
							p.p_tt=new_current_time-p.p_at;
							p.p_wt=p.p_tt-p.p_bt;
							printf("process id:%d   arrival time: %d  burst time:%d  turn around time:%d  waiting time:%d\n",p.p_id,p.p_at,p.p_bt,p.p_tt,p.p_wt);							
							//old_current_time=new_current_time+1;
							removeprocess(p.p_id);
					}
					else
					{
							new_current_time+=1;

							p.p_rt--;
							update_the_process_value(p.p_id,p.p_at,p.p_bt,p.p_rt,p.p_tt,p.p_wt,p.p_pri);
							add_into_remaining_process(new_current_time,new_current_time);
					}
				//	check any new process has com at new time as there is no interval if yes the add else continue

					
				}
				else if((approach==1||approach==3||approach==5))//APPROACH IS NON PREMPTIVE
				{
					
				//	execute it completely remove it from the remaning process
					old_current_time=new_current_time+1;
					new_current_time+=p.p_bt;
					p.p_rt-=p.p_rt;
					p.p_tt=new_current_time-p.p_at;
					p.p_wt=p.p_tt-p.p_bt;
					//print the status of process after completion
					printf("process id:%d   arrival time: %d  burst time:%d  turn around time:%d  waiting time:%d\n",p.p_id,p.p_at,p.p_bt,p.p_tt,p.p_wt);
				//	check for new process between old and new current time add it to queue of remaining process
					add_into_remaining_process(old_current_time,new_current_time);
					removeprocess(p.p_id);
				}
			}
		}
		approach+=1;
	}
	return 0;
}
/*
OUTPUT:
rishi@rishi-PC:~$ ./a.out
FCFS
process id:1   arrival time: 0  burst time:1  turn around time:1  waiting time:0
process id:2   arrival time: 1  burst time:9  turn around time:9  waiting time:0
process id:3   arrival time: 1  burst time:8  turn around time:17  waiting time:9
process id:4   arrival time: 1  burst time:5  turn around time:22  waiting time:17
SHORTEST JOB PREMPTIVE
process id:1   arrival time: 0  burst time:1  turn around time:1  waiting time:0
process id:4   arrival time: 1  burst time:5  turn around time:5  waiting time:0
process id:3   arrival time: 1  burst time:8  turn around time:13  waiting time:5
process id:2   arrival time: 1  burst time:9  turn around time:22  waiting time:13
SHORTEST JOB FIRST NON PREMPTIVE
process id:1   arrival time: 0  burst time:1  turn around time:1  waiting time:0
process id:4   arrival time: 1  burst time:5  turn around time:5  waiting time:0
process id:3   arrival time: 1  burst time:8  turn around time:13  waiting time:5
process id:2   arrival time: 1  burst time:9  turn around time:22  waiting time:13
PRIORITY PREMPTIVE
process id:3   arrival time: 1  burst time:8  turn around time:8  waiting time:0
process id:1   arrival time: 0  burst time:1  turn around time:9  waiting time:8
process id:2   arrival time: 1  burst time:9  turn around time:17  waiting time:8
process id:4   arrival time: 1  burst time:5  turn around time:22  waiting time:17
PRIORITY NON PREMPTIVE
process id:1   arrival time: 0  burst time:1  turn around time:1  waiting time:0
process id:3   arrival time: 1  burst time:8  turn around time:8  waiting time:0
process id:2   arrival time: 1  burst time:9  turn around time:17  waiting time:8
process id:4   arrival time: 1  burst time:5  turn around time:22  waiting time:17
ROUND ROBIN 
process id:1   arrival time: 0  burst time:1  turn around time:1  waiting time:0
process id:4   arrival time: 1  burst time:5  turn around time:17  waiting time:12
process id:3   arrival time: 1  burst time:8  turn around time:21  waiting time:13
process id:2   arrival time: 1  burst time:9  turn around time:22  waiting time:13

*/
